package cate.game.pvp.eliterace.handler;

import cate.game.pvp.eliterace.data.EliteRaceRank;
import cate.game.pvp.eliterace.data.EliteRaceRankData;
import cate.game.rank.RankAdmireConsumer;
import easy.java.practice.errorcode.EcResult;
import org.apache.commons.lang3.StringUtils;
import reactor.core.publisher.Flux;

import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;

import static cate.game.pvp.eliterace.data.EliteRaceRank.INDEX_NAME;

public class BothEliteRaceRankHandler implements EliteRaceRankHandler {

    private final EliteRaceRankData rankData;

    private final RankAdmireConsumer consumer;
    private final Map<String, Integer> rankIndexMap = new HashMap<>();

    public BothEliteRaceRankHandler(Supplier<EliteRaceRankData> rankDataSupplier,
                                    RankAdmireConsumer consumer) {
        Objects.requireNonNull(rankDataSupplier);
        this.rankData = Objects.requireNonNull(rankDataSupplier.get());
        this.consumer = consumer;
        sortRankThenUpdateIndex();
    }

    @Override
    public void sortRankThenUpdateIndex() {
        rankData.getValueList()
                .sort(Comparator.comparing(EliteRaceRank::getWinCount, Comparator.reverseOrder())
                        .thenComparing(EliteRaceRank::getValue, Comparator.reverseOrder()));

        AtomicInteger counter = new AtomicInteger(0);

        rankData.getValueList()
                .forEach(rank -> rankIndexMap.put(rank.getUid(), counter.incrementAndGet()));
    }

    @Override
    public EcResult<Void> admire(String uid, int rank) {
        EcResult<Void> r = new EcResult<>();
        if (rank < 0 || rank >= rankData.size()) {
            return r.fail("超出排行榜范围");
        }
        EliteRaceRank roleRank = rankData.getRankData(rank);
        if (Objects.isNull(roleRank)) {
            return r.fail("查不到此人数据");
        }
        if (StringUtils.equalsIgnoreCase(roleRank.getOwner().uid, uid)) {
            return r.fail("无法给自己点赞");
        }
        roleRank.admireNum += 1;

        Optional.ofNullable(this.consumer)
                .ifPresent(c -> c.consume(roleRank.owner.base.srvId, roleRank.getUid(), getRankId()));

        return r;
    }

    @Override
    public int getIndex(String uid) {
        return this.rankIndexMap.getOrDefault(uid, -1);
    }

    @Nullable
    @Override
    public EliteRaceRank getData(String uid) {
        return this.rankData.getIndex(INDEX_NAME).get(uid);
    }

    @Override
    public Flux<EliteRaceRank> getRankFlow() {
        return Flux.fromIterable(this.rankData.getValueList());
    }

    @Override
    public void update(EliteRaceRank rank) {
        rankData.addValue(rank);
        rankData.addIndex(INDEX_NAME, rank.getUid(), rank);
    }

    @Override
    public void clear() {
        this.rankData.clear();
    }
}
